'use strict'

module.exports = core

const path = require('path')
const commander = require('commander')
const semver = require('semver')
const colors = require('colors/safe')
const userHome = require('user-home')
const pathExists = require('path-exists').sync
const pkg = require('../package.json')
const log = require('@kac-cli-dev/log')
const exec = require('@kac-cli-dev/exec')
const constant = require('./const')

const program = new commander.Command()

async function core() {
  try {
    await prepare()
    registerCommand()
  } catch (error) {
    log.error(error.message)
  }
}

function registerCommand() {
  program
    .name(Object.keys(pkg.bin)[0])
    .usage('<command> [options]')
    .version(pkg.version)
    .option('-d, --debug', '是否开启调试模式', false)
    .option('-tp, --targetPath <targetPath>', '是否指定本地调试文件路径', '')

  program
    .command('init [projectName]')
    .option('-f, --force', '是否强制初始化项目')
    .action(exec)

  // 开启 debug 模式
  program.on('option:debug', () => {
    const opts = program.opts()
    if (opts.debug) {
      process.env.LOG_LEVEL = 'verbose'
    } else {
      process.env.LOG_LEVEL = 'info'
    }
    log.level = process.env.LOG_LEVEL
  })
  // 指定 targetPath
  program.on('option:targetPath', () => {
    const opts = program.opts()
    if (opts.targetPath) {
      process.env.CLI_TARGET_PATH = opts.targetPath
    }
  })
  // 对未知命令的监听
  program.on('command:*', (obj) => {
    const availableCommand = program.commands.map((cmd) => cmd.name())
    console.log(colors.red('未知的命令:', obj[0]))
    if (availableCommand.length) {
      console.log(colors.red('可用命令:', availableCommand.join(',')))
    }
  })

  program.parse(process.argv)

  if (program.args && program.args.length < 1) {
    program.outputHelp()
  }
}

async function prepare() {
  checkPkgVersion()
  checkRoot()
  checkUserHome()
  checkEnv()
  await checkGlobalVersion()
}

/**
 * 检查版本号
 *  */
function checkPkgVersion() {
  log.notice('cli', pkg.version)
}

/**
 * 检查 root 账号，降级处理
 * 防止使用 root 账户创建文件而引起的一系列权限问题
 */

function checkRoot() {
  const rootCheck = require('root-check')
  rootCheck()
}

/**
 * 检查用户主目录
 */

function checkUserHome() {
  if (!userHome || !pathExists(userHome)) {
    throw new Error(colors.red('当前用户主目录不存在'))
  }
}

function checkEnv() {
  const dotenv = require('dotenv')
  const dotenvPath = path.resolve(userHome, '.env')
  if (pathExists) {
    dotenv.config({ path: dotenvPath })
  }
  createDefaultConfig()
}

function createDefaultConfig() {
  const cliConfig = { home: userHome }
  if (process.env.CLI_HOME) {
    cliConfig['cliHome'] = path.join(userHome, process.env.CLI_HOME)
  } else {
    cliConfig['cliHome'] = path.join(userHome, constant.DEFAULT_CLI_HOME)
  }
  process.env.CLI_HOME_PATH = cliConfig.cliHome
}

async function checkGlobalVersion() {
  // 1. 获取当前版本号和模块名
  const currentVersion = pkg.version
  const npmName = pkg.name
  // 2. 调用 npm API ，获取所有版本号
  const { getNpmSemverVersion } = require('@kac-cli-dev/get-npm-info')
  // 3. 提取所有版本号，比对哪些版本是大于当前版本号
  // 4. 获取最新的版本号，提示用户更新到该版本
  const lastVersion = await getNpmSemverVersion(currentVersion, npmName)
  if (lastVersion && semver.gt(lastVersion, currentVersion)) {
    log.warn(
      '更新提示',
      colors.yellow(
        `请手动更新 ${npmName}，当前版本：${currentVersion}，最新版本：${lastVersion}`
      )
    )
  }
}
